package com.ruiao.car.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruiao.car.constant.Constant;
import com.ruiao.car.dto.*;
import com.ruiao.car.entity.AccountAttach;
import com.ruiao.car.entity.AccountAttachDetail;
import com.ruiao.car.enums.AccountAttachEnum;
import com.ruiao.car.enums.ResultEnum;
import com.ruiao.car.mapper.AccountAttachMapper;
import com.ruiao.car.service.IAccountAttachDetailService;
import com.ruiao.car.service.IAccountAttachService;
import com.ruiao.car.service.IArticlesService;
import com.ruiao.car.utils.AccountHeaderUtil;
import com.ruiao.car.utils.AccountThreadLocal;
import com.ruiao.car.utils.DateUtils;
import com.ruiao.car.utils.SnowflakeIdWorker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 用户附加属性表，存储积分等等信息 服务实现类
 * </p>
 *
 * @author jsonval@163.com
 * @since 2020-06-28
 */
@Service
public class AccountAttachServiceImpl extends ServiceImpl<AccountAttachMapper, AccountAttach> implements IAccountAttachService {

    @Autowired
    private IAccountAttachDetailService accountAttachDetailService;
    @Autowired
    private IArticlesService articlesService;

    @Override
    public ResultDto addArticlesIntegral(ArticlesIntegralDto articlesIntegralDto) {
        AccountHeaderUtil accountThreadLocal =  AccountThreadLocal.get();


        AccountAttachDetail accountAttachDetailExists = accountAttachDetailService.getOne(
                new QueryWrapper<AccountAttachDetail>().lambda()
                        .eq(AccountAttachDetail::getAccountId,accountThreadLocal.getAccount().getId())
                        .eq(AccountAttachDetail::getAttachType,AccountAttachEnum.ARTICLES_INTEGRAL.getAttachType())
                        .eq(AccountAttachDetail::getSourceId,articlesIntegralDto.getArticlesId())
                        .eq(AccountAttachDetail::getSourceType,AccountAttachEnum.ARTICLES_INTEGRAL.getSourceType())
                        .eq(AccountAttachDetail::getStatus,1));

        if(null != accountAttachDetailExists){
            return new ResultDto(ResultEnum.SUCCESS.getErrCode(),"已获取积分");
        }

        AccountAttachDetail accountAttachDetail = AccountAttachDetail.builder()
                .attachType(AccountAttachEnum.ARTICLES_INTEGRAL.getAttachType())
                .attachValue(AccountAttachEnum.ARTICLES_INTEGRAL.getAttachValue())
                .sourceId(articlesIntegralDto.getArticlesId())
                .sourceType(AccountAttachEnum.ARTICLES_INTEGRAL.getSourceType())
                .build();

        saveArticlesIntegral(accountAttachDetail);

        return new ResultDto(ResultEnum.SUCCESS.getErrCode(),"获取积分:"+accountAttachDetail.getAttachValue().intValue(),accountAttachDetail.getAttachValue());

    }

    @Override
    public ResultDto addArticlesIntegralFromIncentiveVideo() {

        Date now = new Date();

        AccountHeaderUtil accountThreadLocal =  AccountThreadLocal.get();
        AccountAttachDetail accountAttachDetailExists = accountAttachDetailService.getOne(
                new QueryWrapper<AccountAttachDetail>().lambda()
                        .eq(AccountAttachDetail::getAccountId,accountThreadLocal.getAccount().getId())
                        .eq(AccountAttachDetail::getAttachType,AccountAttachEnum.ARTICLES_INTEGRAL.getAttachType())
                        .eq(AccountAttachDetail::getSourceType,AccountAttachEnum.INCENTIVE_VIDEO_INTEGRAL.getSourceType())
                        .eq(AccountAttachDetail::getStatus,1).orderByDesc(AccountAttachDetail::getCreateDate).last("limit 1"));

        if(null!=accountAttachDetailExists && DateUtils.diffSecond(accountAttachDetailExists.getCreateDate(),now)<=10){
            return new ResultDto(ResultEnum.SUCCESS.getErrCode(),"已获取积分");
        }

        AccountAttachDetail accountAttachDetail = AccountAttachDetail.builder()
                .attachType(AccountAttachEnum.INCENTIVE_VIDEO_INTEGRAL.getAttachType())
                .attachValue(AccountAttachEnum.INCENTIVE_VIDEO_INTEGRAL.getAttachValue())
                .sourceType(AccountAttachEnum.INCENTIVE_VIDEO_INTEGRAL.getSourceType())
                .build();

        saveArticlesIntegral(accountAttachDetail);

        return new ResultDto(ResultEnum.SUCCESS.getErrCode(),"获取积分:"+accountAttachDetail.getAttachValue().intValue(),accountAttachDetail.getAttachValue());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveArticlesIntegral(AccountAttachDetail accountAttachDetail){
        AccountHeaderUtil accountThreadLocal =  AccountThreadLocal.get();
        AccountAttach accountAttach = this.getOne(new QueryWrapper<AccountAttach>().lambda().
                eq(AccountAttach::getAccountId,accountThreadLocal.getAccount().getId()));
        if(null == accountAttach){
            accountAttach = AccountAttach.builder().accountId(accountThreadLocal.getAccount().getId())
                    .mltAddress(Constant.MLT_PRE+SnowflakeIdWorker.getInstance().nextId())
                    .appId(accountThreadLocal.getAccount().getAppId()).integralTotal(new BigDecimal(0)).build();
        }

        accountAttachDetail.setAccountId(accountAttach.getAccountId());
        accountAttachDetail.setAppId(accountAttach.getAppId());

        accountAttach.setIntegralTotal(accountAttach.getIntegralTotal().add(accountAttachDetail.getAttachValue()));
        accountAttach.setUpdateDate(new Date());


        accountAttachDetailService.save(accountAttachDetail);
        this.saveOrUpdate(accountAttach);

    }

    @Override
    public ResultDto<ArticlesIntegralTotalDto> getPage(Page page) {
        AccountHeaderUtil accountThreadLocal =  AccountThreadLocal.get();
        IPage<AccountAttachDetail> pageList = accountAttachDetailService.page(page,
                new QueryWrapper<AccountAttachDetail>().lambda()
                        .eq(AccountAttachDetail::getAccountId,accountThreadLocal.getAccount().getId())
                        .eq(AccountAttachDetail::getAttachType,AccountAttachEnum.ARTICLES_INTEGRAL.getAttachType())
                        .eq(AccountAttachDetail::getStatus,1).orderByDesc(AccountAttachDetail::getCreateDate));



        IPage<ArticlesIntegralDetailDto> pageResult = new Page<>();

        List<ArticlesIntegralDetailDto> articlesIntegralDetailDtoList = new ArrayList<>(pageList.getRecords().size());

        pageList.getRecords().forEach(accountAttachDetail->{
            ArticlesIntegralDetailDto articlesIntegralDetailDto = new ArticlesIntegralDetailDto();
            articlesIntegralDetailDto.setAttachValue(accountAttachDetail.getAttachValue().intValue());
            //articlesIntegralDetailDto.setArticles(articlesService.getById(accountAttachDetail.getSourceId()));
            articlesIntegralDetailDto.setCreateDate(accountAttachDetail.getCreateDate());
            articlesIntegralDetailDto.setSourceType(accountAttachDetail.getSourceType());
            articlesIntegralDetailDto.setSourceId(accountAttachDetail.getSourceId());
            articlesIntegralDetailDtoList.add(articlesIntegralDetailDto);
        });

        pageResult.setRecords(articlesIntegralDetailDtoList);
        pageResult.setTotal(pageList.getTotal());
        pageResult.setSize(pageList.getSize());
        pageResult.setCurrent(pageList.getCurrent());
        pageResult.setPages(pageList.getPages());

        ArticlesIntegralTotalDto articlesIntegralTotalDto = new ArticlesIntegralTotalDto();
        articlesIntegralTotalDto.setArticlesIntegralPageInfo(pageResult);

        AccountAttach accountAttach = getOne(
                new QueryWrapper<AccountAttach>().lambda().eq(AccountAttach::getAccountId,accountThreadLocal.getAccount().getId()));

        if(null!=accountAttach){
            articlesIntegralTotalDto.setIntegralTotal(accountAttach.getIntegralTotal());
            articlesIntegralTotalDto.setMltAddress(accountAttach.getMltAddress());
        }

        return new ResultDto(ResultEnum.SUCCESS, articlesIntegralTotalDto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDto giveArticlesIntegral(ArticlesIntegralGiveDto articlesIntegralGiveDto) {
        AccountHeaderUtil accountThreadLocal =  AccountThreadLocal.get();
        AccountAttach accountAttach = this.getOne(new QueryWrapper<AccountAttach>().lambda().
                eq(AccountAttach::getAccountId,accountThreadLocal.getAccount().getId()));
        if(null == accountAttach || accountAttach.getIntegralTotal().compareTo(articlesIntegralGiveDto.getIntegral())<0){
            return new ResultDto(ResultEnum.ILLEGAL_PARAM.getErrCode(),"可用不足");
        }

        if(accountAttach.getMltAddress().equals(articlesIntegralGiveDto.getMltAddress())){
            return new ResultDto(ResultEnum.ILLEGAL_PARAM.getErrCode(),"不能转赠给自己");
        }

        //被赠送方
        AccountAttach accountAttachGived = this.getOne(new QueryWrapper<AccountAttach>().lambda().
                eq(AccountAttach::getMltAddress,articlesIntegralGiveDto.getMltAddress()));

        if(null == accountAttachGived){
            return new ResultDto(ResultEnum.ILLEGAL_PARAM.getErrCode(),"对方地址不存在");
        }

        AccountAttachDetail accountAttachDetail = AccountAttachDetail.builder().accountId(accountAttach.getAccountId())
                .appId(accountAttach.getAppId()).attachType(AccountAttachEnum.GIVE_INTEGRAL.getAttachType())
                .attachValue(new BigDecimal("-"+articlesIntegralGiveDto.getIntegral().toString()))
                .sourceId(accountAttachGived.getMltAddress())
                .sourceType(AccountAttachEnum.GIVE_INTEGRAL.getSourceType())
                .build();
        accountAttach.setIntegralTotal(accountAttach.getIntegralTotal().subtract(articlesIntegralGiveDto.getIntegral())).setUpdateDate(new Date());

        BigDecimal integralFinal = articlesIntegralGiveDto.getIntegral().multiply(Constant.MLT_PRE_GIVE_RATE).setScale(2, BigDecimal.ROUND_HALF_UP);

        AccountAttachDetail accountAttachDetailGived = AccountAttachDetail.builder().accountId(accountAttachGived.getAccountId())
                .appId(accountAttach.getAppId()).attachType(AccountAttachEnum.GIVED_INTEGRAL.getAttachType())
                .attachValue(integralFinal)
                .sourceId(accountAttach.getMltAddress())
                .sourceType(AccountAttachEnum.GIVED_INTEGRAL.getSourceType())
                .build();
        accountAttachGived.setIntegralTotal(accountAttachGived.getIntegralTotal().add(integralFinal)).setUpdateDate(new Date());

        this.updateById(accountAttach);
        accountAttachDetailService.save(accountAttachDetail);

        this.updateById(accountAttachGived);
        accountAttachDetailService.save(accountAttachDetailGived);

        return new ResultDto(ResultEnum.SUCCESS,"转赠成功");

    }

}
